/**
 * created by 小卷毛, 2021-05-21
 * Copyright (c) 2021, 416143467@qq.com All Rights Reserved.
 * #                   *********                            #
 * #                  ************                          #
 * #                  *************                         #
 * #                 **  ***********                        #
 * #                ***  ****** *****                       #
 * #                *** *******   ****                      #
 * #               ***  ********** ****                     #
 * #              ****  *********** ****                    #
 * #            *****   ***********  *****                  #
 * #           ******   *** ********   *****                #
 * #           *****   ***   ********   ******              #
 * #          ******   ***  ***********   ******            #
 * #         ******   **** **************  ******           #
 * #        *******  ********************* *******          #
 * #        *******  ******************************         #
 * #       *******  ****** ***************** *******        #
 * #       *******  ****** ****** *********   ******        #
 * #       *******    **  ******   ******     ******        #
 * #       *******        ******    *****     *****         #
 * #        ******        *****     *****     ****          #
 * #         *****        ****      *****     ***           #
 * #          *****       ***        ***      *             #
 * #            **       ****        ****                   #
 */
package com.rzico.sbl.viewmodel

import androidx.lifecycle.MutableLiveData
import com.amap.api.convertToLatLng
import com.amap.api.maps.AMapUtils
import com.amap.api.services.core.LatLonPoint
import com.google.android.material.tabs.TabLayout
import com.lzg.extend.BaseResponse
import com.lzg.extend.jackson.JacksonConvert
import com.lzg.okrx.RxSingleHelper
import com.lzg.okrx.adapter.FlowableBody
import com.lzy.okgo.OkGo
import com.lzy.okgo.model.HttpMethod
import com.rzico.sbl.R
import com.rzico.sbl.model.*
import com.rzico.sbl.other.OrderService
import com.xinnuo.common.extend.condition
import com.xinnuo.common.extend.conditionIf
import com.xinnuo.common.extend.find
import com.xinnuo.common.extend.formatDecimal
import com.xinnuo.common.helper.doubleValue
import com.xinnuo.common.helper.getTimeString
import com.xinnuo.common.helper.intValue
import com.xinnuo.common_ui.base.addItems
import com.xinnuo.common_ui.utils.applyFlowableSchedulers
import com.xinnuo.common_ui.utils.applySchedulers
import com.xinnuo.common_ui.utils.subscribeByFinally
import com.xinnuo.common_ui.view.BadgeTextView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
 * 描 述：运单操作相关
 * 作 者：小卷毛  2021-05-21 13:30
 * 修改描述：
 * 修 改 人：
 * 修改版本：
 */
class DeliverViewModel : CommonViewModel() {

    val mBarrelEvent = MutableLiveData<ArrayList<CommonData>>()
    val mTicketEvent = MutableLiveData(0)
    val mPayEvent = MutableLiveData<ArrayList<CommonData>>()

    /**
     * 获取运单列表
     */
    fun deliverList(
        page: Int,
        userId: String,
        roleId: String,
        serviceId: String,
        state: String,
        keyWord: String,
        onSuccess: (ArrayList<Any>) -> Unit = {},
        onFinally: () -> Unit = {}
    ) = mDisposables.add(
        OkGo.post<BaseResponse<OrderModel>>(BaseUrl.deliverList)
            .isMultipart(true)
            .params(
                getParams(
                    "status" to state,
                    "searchValue" to keyWord,
                    "pageStart" to page * 10,
                    "pageSize" to 10
                )
            )
            .converter(object : JacksonConvert<BaseResponse<OrderModel>>() {})
            .adapt(FlowableBody())
            .compose(applyFlowableSchedulers())
            .map {
                ArrayList<Any>().apply {
                    it.data.data.forEachIndexed { index, item ->
                        add(OrderHeader().apply {
                            position = index
                            hint = "下单时间: "
                            orderSN = item.orderSn
                            shippingSn = item.sn
                            shipId = item.id
                            status_hint = item.statusDescr
                            time = item.orderDate.getTimeString()
                        })
                        addItems(
                            item.shippingItems
                                .onEach {
                                    it.orderSN = item.orderSn
                                    it.shippingSn = item.sn
                                    it.shipId = item.id
                                    it.position = index
                                    it.hopeDate = item.hopeDate.orEmpty()
                                    it.reminderDate = item.reminderDate.orEmpty()
                                    it.methodDescr = item.methodDescr.orEmpty()
                                    it.fast = item.isFast
                                    it.first = item.isFisrst
                                }
                        )
                        add(OrderFooter().apply {
                            position = index
                            id = item.id
                            orderSN = item.orderSn
                            shippingSn = item.sn
                            status = item.status.orEmpty()
                            total_num = item.quantity
                            amount = item.amount.orEmpty()
                            name = item.consignee.orEmpty()
                            phone = item.phone.orEmpty()
                            address = item.address
                            lng = if (item.lng.doubleValue > 0) item.lng else ""
                            lat = if (item.lat.doubleValue > 0) item.lat else ""
                            cardMemo = item.cardMemo.orEmpty()
                            memo = item.memo.orEmpty()
                            shipMemo = item.shipMemo.orEmpty().trimEnd('\n')
                            adminName = item.adminName.orEmpty()
                            adminPhone = item.adminPhone.orEmpty()
                            adminMemberId = item.adminMember.orEmpty()
                            hopeDate = item.hopeDate.getTimeString()
                            estimateDate = item.estimateDate.orEmpty()
                            deliveryDate = item.deliveryDate.getTimeString()
                            allowRob = item.allowRob
                            meituanShopName = item.meituanShopName.orEmpty()
                            freight = item.adminFreight.orEmpty()

                            when (status) {
                                "unconfirmed" -> when (roleId) {
                                    "1", "2", "10" -> {
                                        hint_btn1 = "派单"
                                        hint_btn2 = conditionIf(
                                            serviceId in OrderService.REJECT_CONTROL,
                                            "驳回",
                                            ""
                                        )
                                    }

                                    "3" -> hint_btn1 = conditionIf(allowRob, "抢单", "")
                                }

                                "undispatch" -> {
                                    (userId == adminMemberId)
                                        .condition {
                                            hint_btn1 = "确认配送"
                                            hint_btn3 = conditionIf(allowRob, "驳回", "")
                                        }
                                }

                                "dispatch" -> {
                                    (userId == adminMemberId)
                                        .condition {
                                            hint_btn1 = "送达"
                                            hint_btn3 = conditionIf(allowRob, "驳回", "")
                                        }

                                    hint_btn2 =
                                        if (lat.isEmpty() || lng.isEmpty()) "" else "一键导航"
                                }

                                "delivery" ->
                                    hint_btn1 = conditionIf(roleId in "1,2", "审核", "")

                                "completed" -> {
                                    if (roleId in "1,2")
                                        hint_btn1 =
                                            if (freight.isEmpty()) "工资结算"
                                            else "工资: ${freight.formatDecimal()} 元"
                                }
                            }
                        })
                    }
                }
            }
            .subscribeByFinally(
                event = this,
                onSuccess = onSuccess,
                onFinally = onFinally
            )
    )

    /**
     * 订单初始数据
     */
    fun deliverDet(orderSN: String) =
        RxSingleHelper.requestString(
            url = BaseUrl.deliverDet,
            params = getParams("sn" to orderSN)
        )
            .compose(applySchedulers())
            .doOnSubscribe { showLoading() }
            .doFinally { dismissLoading() }

    /**
     * 品牌列表
     */
    fun getBarrelList(id: String) =
        requestCommon(
            requestUrl = BaseUrl.barrelList,
            requestMethod = HttpMethod.GET,
            params = arrayOf("shippingId" to id),
            onSuccess = { mBarrelEvent.value = it }
        )

    /**
     * 确认送达初始数据
     */
    fun viewBarrel(orderSN: String) =
        RxSingleHelper.requestString(
            url = BaseUrl.deliverDet,
            params = getParams("sn" to orderSN)
        )
            .compose(applySchedulers())
            .doOnSubscribe { showLoading() }
            .doFinally { dismissLoading() }

    /**
     * 会员水票信息
     */
    fun ticketCount(cardId: String) =
        requestCommon(
            requestUrl = BaseUrl.ticketCount,
            requestMethod = HttpMethod.GET,
            params = arrayOf(
                "cardId" to cardId,
                "subType" to "water"
            ),
            onSuccess = { list ->
                var ticketCount = 0
                list.forEach { ticketCount += it.stock.intValue }

                mTicketEvent.value = ticketCount
            }
        )

    /**
     * 确认送达
     */
    fun deliveryOrder(vararg params: Pair<String, Any>) =
        RxSingleHelper.requestString(
            url = BaseUrl.delivery,
            isMultipart = true,
            params = getParams(*params)
        )
            .compose(applySchedulers())
            .doOnSubscribe { showLoading() }
            .doFinally { dismissLoading() }

    /**
     * 运单送达详情
     */
    fun orderInfo(orderSN: String) =
        RxSingleHelper.requestString(
            url = BaseUrl.shipInit,
            params = getParams("sn" to orderSN)
        )
            .compose(applySchedulers())
            .doOnSubscribe { showLoading() }
            .doFinally { dismissLoading() }

    /**
     * 抢单 BaseUrl.deliveryGrb
     * 驳回 BaseUrl.deliveryBak
     * 打单 BaseUrl.deliveryPrt
     */
    fun operateOrder(
        url: String,
        shippingSN: String,
        isPost: Boolean = true
    ) =
        RxSingleHelper.requestString(
            method = if (isPost) HttpMethod.POST else HttpMethod.GET,
            url = url,
            params = getParams("sn" to shippingSN)
        )
            .compose(applySchedulers())
            .doOnSubscribe { showLoading() }
            .doFinally { dismissLoading() }

    /**
     * 工资结算
     */
    fun salaryOrder(shippingSN: String, amount: String) =
        RxSingleHelper.requestString(
            url = BaseUrl.deliveryFgt,
            params = getParams(
                "sn" to shippingSN,
                "freight" to amount,
            )
        )
            .compose(applySchedulers())
            .doOnSubscribe { showLoading() }
            .doFinally { dismissLoading() }

    /**
     * 运单转派、派单
     */
    fun deliveryDph(
        shippingSn: String,
        shopId: String,
        adminId: String,
        transfer: Boolean,
        price: String,
        memo: String
    ) = RxSingleHelper.requestString(
        url = BaseUrl.deliveryDph,
        isMultipart = true,
        params = getParams(
            "sn" to shippingSn,
            "shopId" to shopId,
            "adminId" to adminId,
            "transfer" to transfer,
            "settlementPrice" to price,
            "memo" to memo
        )
    )
        .compose(applySchedulers())
        .doOnSubscribe { showLoading() }
        .doFinally { dismissLoading() }

    /**
     * 运单审核
     */
    fun deliveryReview(vararg params: Pair<String, Any>) =
        RxSingleHelper.requestString(
            url = BaseUrl.deliveryRev,
            isMultipart = true,
            params = getParams(*params)
        )
            .compose(applySchedulers())
            .doOnSubscribe { showLoading() }
            .doFinally { dismissLoading() }

    /**
     * 获取批量送达列表
     */
    fun batchList(
        page: Int,
        state: String,
        onSuccess: (ArrayList<OrderData>) -> Unit = {},
        onFinally: () -> Unit = {}
    ) = mDisposables.add(
        OkGo.get<BaseResponse<OrderModel>>(BaseUrl.deliverList)
            .params(
                getParams(
                    "type" to "batch",
                    "status" to state,
                    "pageStart" to page * 20,
                    "pageSize" to 20
                )
            )
            .converter(object : JacksonConvert<BaseResponse<OrderModel>>() {})
            .adapt(FlowableBody())
            .compose(applyFlowableSchedulers())
            .map { it.data.data }
            .subscribeByFinally(
                event = this,
                onSuccess = onSuccess,
                onFinally = onFinally
            )
    )

    /**
     * 付款方式
     */
    fun getPayment() =
        requestCommon(
            isLoading = true,
            requestUrl = BaseUrl.manuWay,
            requestMethod = HttpMethod.GET,
            onSuccess = { mPayEvent.value = it }
        )

    /**
     * 获取配送中运单列表
     */
    fun routeList(
        onSuccess: (List<OrderData>) -> Unit = {},
        onFinally: () -> Unit = {}
    ) = mDisposables.add(
        OkGo.get<BaseResponse<OrderModel>>(BaseUrl.deliverList)
            .params(
                getParams(
                    "status" to "dispatch",
                    "searchValue" to "",
                    "pageStart" to 0,
                    "pageSize" to 1000
                )
            )
            .converter(object : JacksonConvert<BaseResponse<OrderModel>>() {})
            .adapt(FlowableBody())
            .compose(applyFlowableSchedulers())
            .doOnSubscribe { showLoading() }
            .doFinally { dismissLoading() }
            .map { response ->
                response.data
                    .data
                    .filter {
                        it.lat.doubleValue > 0 && it.lng.doubleValue > 0
                    }
            }
            .subscribeByFinally(
                event = this,
                onSuccess = onSuccess,
                onFinally = onFinally
            )
    )

    /**
     * 获取距离参考点最近的坐标点
     */
    suspend fun sortPoints(
        refer: LatLonPoint,
        points: ArrayList<LatLngBean>
    ) =
        withContext(Dispatchers.IO) {
            points.forEach {
                it.distance = AMapUtils.calculateLineDistance(
                    it.point.convertToLatLng(),
                    refer.convertToLatLng()
                )
            }

            return@withContext sortByDistance(refer, points, arrayListOf())
        }

    /**
     * 递归调用进行排序
     */
    private fun sortByDistance(
        point: LatLonPoint,
        from: ArrayList<LatLngBean>,
        to: ArrayList<LatLngBean>
    ): ArrayList<LatLngBean> {
        from.forEach {
            it.preDistance = AMapUtils.calculateLineDistance(
                it.point.convertToLatLng(),
                point.convertToLatLng()
            )
        }

        // 根据距离排序
        from.sortBy { it.preDistance }

        return if (from.size == 1) {
            to.apply { add(from[0]) }
        } else {
            to.add(from.removeFirst())
            sortByDistance(to.last().point, from, to)
        }
    }

    /**
     * 运单数量
     */
    fun orderCount() =
        RxSingleHelper
            .requestString(url = BaseUrl.deliverCount)
            .compose(applySchedulers())
            .doOnSubscribe { }
            .doFinally { }

    /**
     * 更新自定义Tab数量
     */
    fun updateNum(
        unconfirmed: String,
        undispatch: String,
        confirmed: String,
        layout: TabLayout
    ) {
        layout.getTabAt(0)?.let { tab ->
            tab.customView
                ?.find<BadgeTextView>(R.id.item_tab_num)
                ?.setBadgeCount(unconfirmed)
        }
        layout.getTabAt(1)?.let { tab ->
            tab.customView
                ?.find<BadgeTextView>(R.id.item_tab_num)
                ?.setBadgeCount(undispatch)
        }
        layout.getTabAt(2)?.let { tab ->
            tab.customView
                ?.find<BadgeTextView>(R.id.item_tab_num)
                ?.setBadgeCount(confirmed)
        }
    }

}